package repository

import (
	"fitness/go-admin/internal/model"
	"time"

	"gorm.io/gorm"
)

type BookingRepository interface {
	Create(booking *model.CourseBooking) error
	GetByID(id uint) (*model.CourseBooking, error)
	GetByUserAndCourse(userID, courseID uint) (*model.CourseBooking, error)
	List(req *model.BookingListReq) ([]model.BookingListItem, int64, error)
	ListByUser(userID uint, req *model.BookingListReq) ([]model.BookingListItem, int64, error)
	ListByCourse(courseID uint, req *model.BookingListReq) ([]model.BookingListItem, int64, error)
	Update(booking *model.CourseBooking) error
	Delete(id uint) error
	CountByCourse(courseID uint, status int) (int64, error)
	CheckTimeConflict(userID uint, startTime, endTime time.Time, excludeBookingID uint) (bool, error)
}

type bookingRepository struct {
	db *gorm.DB
}

func NewBookingRepository(db *gorm.DB) BookingRepository {
	return &bookingRepository{db: db}
}

func (r *bookingRepository) Create(booking *model.CourseBooking) error {
	return r.db.Create(booking).Error
}

func (r *bookingRepository) GetByID(id uint) (*model.CourseBooking, error) {
	var booking model.CourseBooking
	err := r.db.Preload("Course").Preload("Member").Preload("User").First(&booking, id).Error
	return &booking, err
}

func (r *bookingRepository) GetByUserAndCourse(userID, courseID uint) (*model.CourseBooking, error) {
	var booking model.CourseBooking
	err := r.db.Where("user_id = ? AND course_id = ? AND status = ?", userID, courseID, model.BookingStatusBooked).
		First(&booking).Error
	return &booking, err
}

// List 管理员查看所有预约
func (r *bookingRepository) List(req *model.BookingListReq) ([]model.BookingListItem, int64, error) {
	var items []model.BookingListItem
	var total int64

	query := r.db.Table("course_bookings").
		Select(`course_bookings.id, course_bookings.course_id, courses.name as course_name, 
			courses.start_time as course_time, course_bookings.member_id, members.name as member_name,
			course_bookings.user_id, users.username, course_bookings.status, 
			course_bookings.booked_at, course_bookings.cancelled_at, course_bookings.check_in_at,
			course_bookings.cancel_reason, course_bookings.created_at`).
		Joins("LEFT JOIN courses ON course_bookings.course_id = courses.id").
		Joins("LEFT JOIN members ON course_bookings.member_id = members.id").
		Joins("LEFT JOIN users ON course_bookings.user_id = users.id")

	// 筛选条件
	if req.CourseID != nil {
		query = query.Where("course_bookings.course_id = ?", *req.CourseID)
	}
	if req.MemberID != nil {
		query = query.Where("course_bookings.member_id = ?", *req.MemberID)
	}
	if req.Status != nil {
		query = query.Where("course_bookings.status = ?", *req.Status)
	}
	if req.StartDate != "" {
		query = query.Where("DATE(courses.start_time) >= ?", req.StartDate)
	}
	if req.EndDate != "" {
		query = query.Where("DATE(courses.start_time) <= ?", req.EndDate)
	}
	if req.Keyword != "" {
		keyword := "%" + req.Keyword + "%"
		query = query.Where("members.name LIKE ? OR courses.name LIKE ?", keyword, keyword)
	}

	// 获取总数
	query.Count(&total)

	// 分页
	page := req.Page
	if page < 1 {
		page = 1
	}
	pageSize := req.PageSize
	if pageSize < 1 {
		pageSize = 10
	}
	if pageSize > 100 {
		pageSize = 100
	}

	offset := (page - 1) * pageSize
	err := query.Order("course_bookings.created_at DESC").
		Limit(pageSize).Offset(offset).
		Scan(&items).Error

	// 设置状态文本
	for i := range items {
		items[i].StatusText = model.GetBookingStatusText(items[i].Status)
	}

	return items, total, err
}

// ListByUser 获取用户的预约列表
func (r *bookingRepository) ListByUser(userID uint, req *model.BookingListReq) ([]model.BookingListItem, int64, error) {
	var items []model.BookingListItem
	var total int64

	query := r.db.Table("course_bookings").
		Select(`course_bookings.id, course_bookings.course_id, courses.name as course_name, 
			courses.start_time as course_time, course_bookings.member_id, members.name as member_name,
			course_bookings.user_id, users.username, course_bookings.status, 
			course_bookings.booked_at, course_bookings.cancelled_at, course_bookings.check_in_at,
			course_bookings.cancel_reason, course_bookings.created_at`).
		Joins("LEFT JOIN courses ON course_bookings.course_id = courses.id").
		Joins("LEFT JOIN members ON course_bookings.member_id = members.id").
		Joins("LEFT JOIN users ON course_bookings.user_id = users.id").
		Where("course_bookings.user_id = ?", userID)

	// 筛选条件
	if req.Status != nil {
		query = query.Where("course_bookings.status = ?", *req.Status)
	}
	if req.StartDate != "" {
		query = query.Where("DATE(courses.start_time) >= ?", req.StartDate)
	}
	if req.EndDate != "" {
		query = query.Where("DATE(courses.start_time) <= ?", req.EndDate)
	}

	// 获取总数
	query.Count(&total)

	// 分页
	page := req.Page
	if page < 1 {
		page = 1
	}
	pageSize := req.PageSize
	if pageSize < 1 {
		pageSize = 10
	}
	if pageSize > 100 {
		pageSize = 100
	}

	offset := (page - 1) * pageSize
	err := query.Order("course_bookings.created_at DESC").
		Limit(pageSize).Offset(offset).
		Scan(&items).Error

	// 设置状态文本
	for i := range items {
		items[i].StatusText = model.GetBookingStatusText(items[i].Status)
	}

	return items, total, err
}

// ListByCourse 获取课程的预约列表
func (r *bookingRepository) ListByCourse(courseID uint, req *model.BookingListReq) ([]model.BookingListItem, int64, error) {
	var items []model.BookingListItem
	var total int64

	query := r.db.Table("course_bookings").
		Select(`course_bookings.id, course_bookings.course_id, courses.name as course_name, 
			courses.start_time as course_time, course_bookings.member_id, members.name as member_name,
			course_bookings.user_id, users.username, course_bookings.status, 
			course_bookings.booked_at, course_bookings.cancelled_at, course_bookings.check_in_at,
			course_bookings.cancel_reason, course_bookings.created_at`).
		Joins("LEFT JOIN courses ON course_bookings.course_id = courses.id").
		Joins("LEFT JOIN members ON course_bookings.member_id = members.id").
		Joins("LEFT JOIN users ON course_bookings.user_id = users.id").
		Where("course_bookings.course_id = ?", courseID)

	// 筛选条件
	if req.Status != nil {
		query = query.Where("course_bookings.status = ?", *req.Status)
	}
	if req.Keyword != "" {
		keyword := "%" + req.Keyword + "%"
		query = query.Where("members.name LIKE ? OR users.username LIKE ?", keyword, keyword)
	}

	// 获取总数
	query.Count(&total)

	// 分页
	page := req.Page
	if page < 1 {
		page = 1
	}
	pageSize := req.PageSize
	if pageSize < 1 {
		pageSize = 10
	}
	if pageSize > 100 {
		pageSize = 100
	}

	offset := (page - 1) * pageSize
	err := query.Order("course_bookings.created_at DESC").
		Limit(pageSize).Offset(offset).
		Scan(&items).Error

	// 设置状态文本
	for i := range items {
		items[i].StatusText = model.GetBookingStatusText(items[i].Status)
	}

	return items, total, err
}

func (r *bookingRepository) Update(booking *model.CourseBooking) error {
	return r.db.Save(booking).Error
}

func (r *bookingRepository) Delete(id uint) error {
	return r.db.Delete(&model.CourseBooking{}, id).Error
}

// CountByCourse 统计课程的预约数量（指定状态）
func (r *bookingRepository) CountByCourse(courseID uint, status int) (int64, error) {
	var count int64
	err := r.db.Model(&model.CourseBooking{}).
		Where("course_id = ? AND status = ?", courseID, status).
		Count(&count).Error
	return count, err
}

// CheckTimeConflict 检查时间冲突（同一用户同一时间段已有其他预约）
func (r *bookingRepository) CheckTimeConflict(userID uint, startTime, endTime time.Time, excludeBookingID uint) (bool, error) {
	var count int64
	query := r.db.Table("course_bookings").
		Joins("JOIN courses ON course_bookings.course_id = courses.id").
		Where("course_bookings.user_id = ?", userID).
		Where("course_bookings.status IN (?)", []int{model.BookingStatusBooked, model.BookingStatusCheckedIn}).
		Where("((courses.start_time < ? AND courses.end_time > ?) OR (courses.start_time < ? AND courses.end_time > ?))",
			endTime, startTime, endTime, endTime)

	if excludeBookingID > 0 {
		query = query.Where("course_bookings.id != ?", excludeBookingID)
	}

	err := query.Count(&count).Error
	return count > 0, err
}
